package com.lagou.sqlSession;


import com.lagou.config.BoundSql;
import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;
import com.lagou.utils.GenericTokenParser;
import com.lagou.handler.ParameterHandler;
import com.lagou.utils.ParameterMapping;
import com.lagou.handler.ParameterMappingTokenHandler;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class SimpleExecutor implements Executor {

	private Connection connection;

	private void getConnection(Configuration configuration) throws SQLException {
		this.connection =  configuration.getDataSource().getConnection();
	}

	public PreparedStatement preExecute(Configuration configuration, MappedStatement mappedStatement, Object[] params) throws Exception {
		//获取连接
		getConnection(configuration);

		String sql = mappedStatement.getSql();
		//解析原sql的占位符为？
		BoundSql boundSql = getBoundSql(sql);

		//获取sql入参类型
		Class<?> paramterType = mappedStatement.getParamterType();

		//预编译
		PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());

		//解析入参
		ParameterHandler parameterHandler = new ParameterHandler();
		parameterHandler.parse(preparedStatement, paramterType, boundSql.getParameterMappingList(),params);
		return preparedStatement;
	}

	@Override
	public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
		PreparedStatement preparedStatement = preExecute(configuration, mappedStatement, params);

		ResultSet resultSet = preparedStatement.executeQuery();
		//对返回结果封装赋值
		Class<?> resultType = mappedStatement.getResultType();
		ResultSetHandler<E> resultSetHandler = new ResultSetHandler<>();
		List<E> results = (List<E>) resultSetHandler.parse(resultSet, resultType);
		return results;
	}


	@Override
	public <E> E update(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
		PreparedStatement preparedStatement = preExecute(configuration, mappedStatement, params);
		Integer resultSet = preparedStatement.executeUpdate();
		//对返回结果封装赋值
		Class<?> resultType = mappedStatement.getResultType();
		ResultSetHandler<E> resultSetHandler = new ResultSetHandler<>();
		E result = (E) resultSetHandler.parse(resultSet, resultType);
		return result;
	}

	private Class<?> getClassType(String paramterType) throws ClassNotFoundException {
		if (paramterType != null) {
			Class<?> aClass = Class.forName(paramterType);
			return aClass;
		}
		return null;

	}


	/**
	 * 完成对#{}的解析工作：1.将#{}使用？进行代替，2.解析出#{}里面的值进行存储
	 *
	 * @param sql
	 * @return
	 */
	private BoundSql getBoundSql(String sql) {
		//标记处理类：配置标记解析器来完成对占位符的解析处理工作
		ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
		GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
		//解析出来的sql
		String parseSql = genericTokenParser.parse(sql);
		//#{}里面解析出来的参数名称
		List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();

		BoundSql boundSql = new BoundSql(parseSql, parameterMappings);
		return boundSql;

	}


}
